/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package th.manager;

import com.google.inject.Inject;
import com.wideplay.warp.persist.Transactional;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import net.sourceforge.stripes.util.Base64;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import th.dao.AkaunDAO;
import th.dao.PenggunaDAO;
import th.dao.SejarahKataLaluanDAO;
import th.model.Akaun;
import th.model.Pengguna;
import th.model.SejarahKatalaluan;

/**
 *
 * @author fikri
 */
public class UserManager {
    
    @Inject
    protected com.google.inject.Provider<Session> sessionProvider;
    @Inject private PenggunaDAO penggunaDAO;
    @Inject private AkaunDAO akaunDAO;
    @Inject private SejarahKataLaluanDAO sejarahKataLaluanDAO;
    

    public boolean authenticate(String userId, String password) {
        String encrypted = encrypt(password);
        Session session = sessionProvider.get();
        Query query = session.createQuery(
                "select p from Pengguna p " +
                "where idPengguna = :userId and password = :password");
        query.setString("userId", userId);
        query.setString("password", encrypted);
        

        Pengguna user = (Pengguna) query.uniqueResult();
        return user != null;
    }
    
     public List<Pengguna> findAll() {
        String query = "SELECT a FROM Pengguna a WHERE a.idPengguna is not null ";
        Query q = sessionProvider.get().createQuery(query);
        return q.list();
    } 
     
    public Pengguna findUser ( String noPengenalan, String noAkaun ) {
        String query = "SELECT a FROM Pengguna a WHERE a.noKp = :noKp ";
        if (StringUtils.isNotBlank(noAkaun)) {
            query += "and a.noKp = ( select distinct b.pengguna.noKp from Akaun b where b.akaunTmbhn = :akaun) ";
        }
        Query q = sessionProvider.get().createQuery(query).setString("noKp", noPengenalan);
        if (StringUtils.isNotBlank(noAkaun)) q.setParameter("akaun", noAkaun);
        return (Pengguna)q.uniqueResult();        
    }
    
    public Pengguna findUserByIdUser( String idUser ) {
        String query = "SELECT a FROM Pengguna a WHERE a.idPengguna = :id";
        Query q = sessionProvider.get().createQuery(query).setString("id", idUser);
        return (Pengguna)q.uniqueResult();   
    }
    
    public Pengguna findUserByIdUser( String idUser, String status ) {
        String query = "SELECT a FROM Pengguna a WHERE a.idPengguna = :id and a.active = :status";
        Query q = sessionProvider.get().createQuery(query).setString("id", idUser).setParameter("status", status);
        return (Pengguna)q.uniqueResult();   
    }
    
    //added in 27/06/2013 
    public Pengguna findUserByIdUser2( String idUser, String noPengenalan ) {
        String query = "SELECT a FROM Pengguna a WHERE a.idPengguna = :id and a.noKp = :noKp";
        Query q = sessionProvider.get().createQuery(query).setString("id", idUser).setParameter("noKp", noPengenalan);
        return (Pengguna)q.uniqueResult();   
    }
    
    @Transactional
    public void updatePengguna(Pengguna pengguna) {
        penggunaDAO.saveOrUpdate(pengguna);
    }
    //bugs : user change noKp at kaunter, mytaha should update in the table
    @Transactional
    public void updatePengguna(String noAkaun, String newKP, String oldKP) {
        String hql = "UPDATE Pengguna set noKp = :newKp "
                + "WHERE noKp = :oldKp";
        Query query = sessionProvider.get().createQuery(hql);
        query.setParameter("newKp", newKP.trim());
        query.setParameter("oldKp", oldKP);
        query.executeUpdate();
        
        hql = "UPDATE AkaunFav set noKp = :newKp "
                + "WHERE noKp = :oldKp";
        query = sessionProvider.get().createQuery(hql);
        query.setParameter("newKp", newKP.trim());
        query.setParameter("oldKp", oldKP);
        query.executeUpdate();
        
        hql = "UPDATE Akaun set noPengenalanTmbhn = :newKp "
                + "WHERE noKp = :oldKp AND noPengenalanTmbhn = :oldKp";
        query = sessionProvider.get().createQuery(hql);
        query.setParameter("newKp", newKP.trim());
        query.setParameter("oldKp", oldKP);
        query.executeUpdate();
        
        hql = "UPDATE Akaun set noKp = :newKp "
                + "WHERE noKp = :oldKp";
        query = sessionProvider.get().createQuery(hql);
        query.setParameter("newKp", newKP.trim());
        query.setParameter("oldKp", oldKP);
        query.executeUpdate();
        
    }
    
   @Transactional
    public void deletePengguna(Pengguna p) {
        penggunaDAO.delete(p);
    }
   
   @Transactional
   public void createPengguna(Pengguna p, Akaun a){
       String ecrypt = encrypt(p.getPassword());
       p.setPassword(ecrypt);
       penggunaDAO.save(p);
       akaunDAO.save(a);
       SejarahKatalaluan sj = new SejarahKatalaluan();
       sj.setInfoAudit(a.getInfoAudit());
       sj.setPengguna(p);
       sj.setKataLaluanLama1(p.getPassword());
       sejarahKataLaluanDAO.save(sj);
   }
   
   private synchronized String encrypt(String plainText) {
        MessageDigest md;

        try {
            md = MessageDigest.getInstance("SHA");
        } catch (NoSuchAlgorithmException e) {
            String msg = "SHA not found, encryption cannot continue, no recovery possible";
            throw new RuntimeException(msg, e);
        }

        try {
            md.update(plainText.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            String msg = "UTF-8 encoding not found, no recovery possible";
            throw new RuntimeException(msg, e);
        }

        byte[] raw = md.digest();

        //String pwd = new BASE64Encoder().encode(raw);
        String pwd = Base64.encodeBytes(raw);
        return pwd.length() > 50 ? pwd.substring(0, 50) : pwd;
    }
   
   public static void main(String[] args){
       UserManager um = new UserManager();
       System.out.println("" + um.encrypt("myt@h@123"));
   }
   
}
